/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ejercicio.practica5;

import static java.lang.Thread.sleep;
import java.util.Random;
import java.util.Scanner;

/**
 *
 * @author manolo
 */
public class algoLamport implements Runnable {

    static volatile int[] numero;
    static volatile boolean[] eligiendo;
    private int id;

    public algoLamport(int id) {
        this.id = id;
    }
    
    private void ocupado() {
        Random rm = new Random();
        try {
            sleep(rm.nextInt(1500));
        } catch (InterruptedException ex) {
            System.out.println("Error: " + ex);
        }
    }

    private void SeccionNoCritica() {
        System.out.println("Proceso " + id + " está en la región no critica");
        ocupado();
    }

    private void SeccionCritica() {
        System.out.println("Proceso " + id + " entrando en la sección critica");
        ocupado();
        System.out.println("Proceso " + id + " saliendo de la sección critica");
    }

    private void Lamport() {
        while (true) {
            /* Calcula el número de turno */
            eligiendo[id] = true;
            numero[id] = 1 + maximo(numero);
            eligiendo[id] = false;
            
             /* Compara con todos los hilos */
          for (int j= 0; j < eligiendo.length; j++)  {    
               /* Si el hilo j está calculando su número, espera a que termine */
               while ( eligiendo[j] ) { /* nada */ }    
               /* Si el hilo j tiene más prioridad, espera a que ponga su número a cero */
               /* j tiene más prioridad si su número de turno es más bajo que el de i,  */
               /*  o bien si es el mismo número y además j es menor que i               */
               while ((numero[j] != 0) && (numero[j] < numero[id]))
               { /* nada */ }  
          }
          SeccionCritica();
          numero[id] = 0;
        }
    }

    private int maximo(int[] numero)
    {
        int max = 0;
        
        for(int i=0; i < numero.length;i++)
            if(numero[i]> max)
                max = numero[i];
        return max;
    }
    @Override
    public void run() {
        SeccionNoCritica();
        Lamport();
    }

    public static void main(String[] args) throws InterruptedException {
        int numProcesos;
        Scanner teclado = new Scanner(System.in);

        System.out.print("Introduzca el número de procesos: ");
        numProcesos = teclado.nextInt();

        numero = new int[numProcesos];
        eligiendo = new boolean[numProcesos];

        for (int i = 0; i < numProcesos; i++) {
            numero[i] = 0;
            eligiendo[i] = false;
        }
        
               // Lanzamiento de los hilos/procesos
        Thread[] p = new Thread[numProcesos];
        for (int i = 0; i < numProcesos; i++) {
            p[i] = new Thread(new algoLamport(i));
            p[i].start();
        }

    }
}
